package com.daify.threadlearn.chapter01.order05;

import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

/**
 * @author daify
 * @date 2019-06-10
 */
public class CacheThree<T,K> implements Computable<T,K> {

    private final Map<T,Future<K>> cache = new ConcurrentHashMap<T, Future<K>>();

    private final Computable<T,K> c;

    public CacheThree(Computable<T, K> c) {
        this.c = c;
    }

    public K compute(final T arg) throws Exception {
        Future<K> kFuture = cache.get(arg);
        if (kFuture == null) {
            Callable<K> eval = new Callable<K>() {
                public K call() throws Exception {
                    return c.compute(arg);
                }
            };

            FutureTask<K> futureTask = new FutureTask<K>(eval);
            kFuture = futureTask;
            cache.put(arg,kFuture);
            futureTask.run();
        }
        try {
            return kFuture.get();
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }
}
